package lex.mtd.core;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Logger;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.lex.io.filesystem.FileNameUtilities;
import org.lex.net.ftp.FTPURL;
import org.lex.net.ftp.IFTPClient;

import lex.mtd.core.net.Connector;
import lex.mtd.core.net.DataSourceObserver;
import lex.mtd.core.net.FTPDataSource;
import lex.mtd.core.net.SunHttpDataSource;
import lex.mtd.core.utils.DaemonExecutor;
import lex.mtd.core.utils.LogSet;
import lex.mtd.core.utils.ProtocolUtils;
import lex.mtd.core.utils.ProtocolUtils.Protocol;
import lex.mtd.utils.Logs;

/**
 * <code>DataSourceSet</code>���Զ��̷߳�ʽ�ں�̨���С�<br>
 * ��������Ϊ��<br>
 * ��һȡ��<code>DownloadTask</code>�е����ӣ�������������(������)��<br>
 * <ol>
 * <li>������ӳɹ���֪ͨ<code>observer</code>���µĿ���<code>DataSource</code><br>
 * <li>�������ʧ�ܣ��ȴ�һ��ʱ��󣬳����������ӡ�<br>
 * </ol>
 * �ظ����ϲ��裬ֱ���ɹ�������е����ӣ����߱�ȡ��
 * 
 * @author Daniel Liu
 */
public class DataSourceSet implements Runnable {
	private URLSet urlSet = null;
	private DataSourceObserver observer = null;
	private boolean running = false;
	private int urlIndex = 0;
	private transient final LogSet log;
	private transient final Logger debug = Logs.get(DataSourceSet.class);

	public DataSourceSet(URLSet urlSet, DataSourceObserver observer, LogSet log) {
		this.urlSet = urlSet;
		this.observer = observer;
		this.log = log;
		// if new url was added to DownloadTask, notify me
		// this.urlSet.AddURLListener( new ChangeListener(){
		// @Override
		// public void stateChanged( ChangeEvent e )
		// {
		// connect( String.valueOf( e.getSource() ) );
		// }
		// } );
	}

	public void start() {
		if (true == running)
			return;
		else {
			this.running = true;
			debug.fine("");
			DaemonExecutor.execute(this);
		}
	}

	public void stop() {
		this.running = false;
		debug.fine("");
	}

	int max = 5;

	public void run() {
		int count = 0;
		while (true == running && count < max) {
			this.connect(urlSet.getURL(urlIndex++));
			if (urlIndex >= urlSet.getURLCount())
				urlIndex = 0;
			count++;
		}
	}

	private void connect(final String url) {
		Protocol p = ProtocolUtils.getProtocol(url);
		if (false == p.isSupported()) {
			log.getLog("").error(url, "Protocol not supported");
			return;
		} else if (Protocol.FTP == p) {
			this.connectFTP(url);
		} else if (Protocol.HTTP == p) {
			try {
				this.connectHTTP(new URL(url));
			} catch (MalformedURLException e) {
				log.getLog("").error(url, e.getLocalizedMessage());
			}
		}
	}

	private void connectHTTP( final URL url )
	{
		final ChangeListener callback = new ChangeListener(){
			@Override
			public void stateChanged( ChangeEvent e )
			{
				Object con = e.getSource();
				if( null != con )
				{
					observer
						.dataSourceAvailable( new SunHttpDataSource( url, log.getLog( gen() ) ) );
				}
			}
		};
		DaemonExecutor.execute( new Runnable(){
			public void run()
			{
				Connector.connectHTTP( url, 0, log.getLog( gen() ), callback );
			}
		} );
	}

	private void connectFTP( final String url )
	{
		final ChangeListener l = new ChangeListener(){
			@Override
			public void stateChanged( ChangeEvent e )
			{
				if( null != e.getSource() )
				{
					IFTPClient ftp = (IFTPClient) e.getSource();
					String dir = FTPURL.parseFtpUrl( url ).getPath();
					String file = FileNameUtilities.getFileName( dir, '/' );
					dir = FileNameUtilities.getParentPath( dir, '/' );
					FTPDataSource fds = new FTPDataSource( ftp, dir, file );
					observer.dataSourceAvailable( fds );
				}
			}
		};
		DaemonExecutor.execute( new Runnable(){
			@Override
			public void run()
			{
				Connector.connectFTP( FTPURL.parseFtpUrl( url ), log.getLog( gen() ), l );
			}
		} );
	}

	private static String gen() {
		return Integer.toString(id++);
	}

	static int id = 1;
}
